package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.Constant;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.page.ReplyPageQuery;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.listeners.message.SignInMessage;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author rui
 * @since 2024-07-21
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    //注入mapper，避免循环依赖
    private final InteractionQuestionMapper questionMapper;
    private final RabbitMqHelper mqHelper;
    private final UserClient userClient;
    private final RemarkClient remarkClient;
    private static Set<Long> liked;
    @Override
    public void addReply(ReplyDTO replyDTO) {
        InteractionReply reply = BeanUtil.toBean(replyDTO, InteractionReply.class);
        if(reply == null){
            throw new BadRequestException("请求参数不对劲");
        }
        //1.获取用户id
        Long userId = UserContext.getUser();
        if(userId != null){
            reply.setUserId(userId);
        }
        //2.保存回复信息
        save(reply);

        //2.封装回答表没有的信息，如果是评论，评论数量加1
        boolean isAnswer = replyDTO.getAnswerId()==null; //为ture则说明是回答，否则为评论
        if(!isAnswer){
            //如果是评论的话是有上级回复的id
            lambdaUpdate()
                    .setSql("reply_times = reply_times + 1")
                    .eq(InteractionReply::getId,replyDTO.getAnswerId()).update();
        }

        //4.更新问题表。更新最新回答id，回答数量，管理员未查看，因为有新的评论
        questionMapper.update(null,
                new LambdaUpdateWrapper<InteractionQuestion>()
                        .set(isAnswer, InteractionQuestion::getLatestAnswerId, reply.getAnswerId()) // 当 isAnswer 为 true 时，设置最新回答ID
                        .set(InteractionQuestion::getStatus, QuestionStatus.UN_CHECK)               // 设置问题状态为未检查
                        .setSql(isAnswer, "answer_times = answer_times + 1")                         // 当 isAnswer 为 true 时，回答次数加1
                        .eq(InteractionQuestion::getId, replyDTO.getQuestionId())                    // 条件：问题ID匹配
        );



        //5.如果是学生则更新积分
        if(replyDTO.getIsStudent()){
            mqHelper.send(
                    MqConstants.Exchange.LEARNING_EXCHANGE,
                    MqConstants.Key.WRITE_REPLY,
                    SignInMessage.of(userId,5));
        }
    }

    @Override
    public PageDTO<ReplyVO> pageQueryReply(ReplyPageQuery pageQuery) {
        Page<InteractionReply> page = getInteractionReplyPage(pageQuery,false);
        List<InteractionReply> records = page.getRecords();
        if(CollUtils.isEmpty(records)){
            return PageDTO.empty(0L,0L);
        }
        Set<Long> liked = new HashSet<>();
        //查询需要封装的属性 回答用户信息 被评论用户信息
        Set<Long> userIds = getLongs(records,false);
        List<ReplyVO> replyVOList = getReplyVOS(userIds, records);
        return PageDTO.of(page,replyVOList);
    }

    private Set<Long> getLongs(List<InteractionReply> records,boolean isAdmin) {
        Set<Long> userIds = new HashSet<>();
        Set<Long> answerIds = new HashSet<>();
        for (InteractionReply record : records) {
            if(record!=null){
                if(!record.getAnonymity()||isAdmin){
                    userIds.add(record.getUserId());
                }
                if(!record.getTargetReplyId().equals(0L)){
                    //添加回复目标的回答id，也就是要找出评论目标用户的用户信息
                    answerIds.add(record.getTargetReplyId());
                }
            }
        }
        if(CollUtils.isNotEmpty(answerIds)){
            List<InteractionReply> interactionReplies = listByIds(answerIds);
            if(CollUtils.isNotEmpty(interactionReplies)){
                List<Long> targetUserIds = interactionReplies.stream()
                        .filter(interactionReply -> (!interactionReply.getAnonymity())&&(!isAdmin))
                        .map(InteractionReply::getUserId)
                        .collect(Collectors.toList());
                userIds.addAll(targetUserIds);
            }
            liked = remarkClient.likedQueryByBizIds(new ArrayList<>(answerIds));
        }

        return userIds;
    }

    private List<ReplyVO> getReplyVOS(Set<Long> userIds, List<InteractionReply> records) {
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userDTOMap = new HashMap<>();
        if(CollUtils.isNotEmpty(userDTOS)){
            userDTOMap  = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }

        List<ReplyVO> replyVOList = new ArrayList<>();
        for (InteractionReply record : records) {
            if(record!=null){
                ReplyVO replyVO = BeanUtil.toBean(record, ReplyVO.class);
                UserDTO userDTO = userDTOMap.get(record.getUserId());
                UserDTO targetUserDTO = userDTOMap.get(record.getTargetUserId());
                if(userDTO != null){
                    replyVO.setUserIcon(userDTO.getIcon());
                    replyVO.setUserName(userDTO.getName());
                    replyVO.setUserType(userDTO.getType());
                }
                if(targetUserDTO != null){
                    replyVO.setTargetUserName(targetUserDTO.getName());
                }
                if (liked != null) {
                    replyVO.setLiked(liked.contains(record.getUserId()));
                } else {
                    replyVO.setLiked(false);
                }
                replyVOList.add(replyVO);
            }
        }
        return replyVOList;
    }

    private Page<InteractionReply> getInteractionReplyPage(ReplyPageQuery pageQuery,boolean isHidden) {
        Long answerId = pageQuery.getAnswerId();
        Long questionId = pageQuery.getQuestionId();
        if(answerId == null&&questionId == null){
            throw new BadRequestException("请求参数错误");
        }
        //1判断是否是回答
        boolean isAnswer = answerId == null;
        //2查询回答或者评论的列表
        Page<InteractionReply> page = lambdaQuery()
                .eq(InteractionReply::getAnswerId, answerId == null ? 0L : answerId)
                .eq(questionId != null, InteractionReply::getQuestionId, questionId)
                .eq(!isHidden,InteractionReply::getHidden, false)
                .page(pageQuery.toMpPage(
                        new OrderItem(Constant.DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(Constant.DATA_FIELD_NAME_CREATE_TIME, false)
                ));
        return page;
    }

    @Override
    public PageDTO<ReplyVO> adminReplyPageQuery(ReplyPageQuery pageQuery) {
        Page<InteractionReply> interactionReplyPage = getInteractionReplyPage(pageQuery, true);
        List<InteractionReply> records = interactionReplyPage.getRecords();
        if(CollUtils.isEmpty(records)){
            return PageDTO.empty(0L,0L);
        }
        Set<Long> userIds = getLongs(records, true);
        List<ReplyVO> replyVOS = getReplyVOS(userIds, records);
        return PageDTO.of(interactionReplyPage,replyVOS);
    }
    @Override
    @Transactional
    public void hiddenReply(Long id, Boolean hidden) {
        // 1.查询
        InteractionReply old = getById(id);
        if (old == null) {
            return;
        }

        // 2.隐藏回答
        InteractionReply reply = new InteractionReply();
        reply.setId(id);
        reply.setHidden(hidden);
        updateById(reply);

        //2.1 隐藏了回答后改变问题回答数量
        InteractionQuestion interactionQuestion = questionMapper.selectById(old.getQuestionId());
        if(interactionQuestion != null){
            questionMapper.update(interactionQuestion,new LambdaUpdateWrapper<InteractionQuestion>()
                    .setSql(hidden?"answer_times = answer_times - 1":"answer_times = answer_times + 1")
                            .eq(InteractionQuestion::getId,old.getQuestionId())
                    );
        }
        // 3.隐藏评论，先判断是否是回答，回答才需要隐藏下属评论
        if (old.getAnswerId() != null && old.getAnswerId() != 0) {
            // 3.1.有answerId，说明自己是评论，无需处理
            return;
        }
        // 3.2.没有answerId，说明自己是回答，需要隐藏回答下的评论
        lambdaUpdate()
                .set(InteractionReply::getHidden, hidden)
                .eq(InteractionReply::getAnswerId, id)
                .update();
    }
}
